import logging
import re
from typing import Dict, Any, List

from lxml import etree

from model.models import AnalogChannel, StatusChannel, ACVChn, ACC_Bran, RX, PX, CG, Igap, Bus, Line, \
    TransformerWinding, Transformer

# 设置日志级别
logging.basicConfig(level=logging.INFO)


def safe_int(value):
    try:
        return int(value) if value else None
    except ValueError:
        return None


def safe_float(value):
    try:
        return float(value) if value else None
    except ValueError:
        return None

class DMFParser:
    """DMF文件解析器包装类，提供与INFParser类似的接口"""
    
    def __init__(self):
        self.lines: List[Dict] = []
        self.buses: List[Dict] = []
        self.transformers: List[Dict] = []
        self.file_info: Dict[str, Any] = {}
        self.raw_data: Dict[str, Any] = {}
        
    def parse_file(self, file_path: str) -> bool:
        """
        解析DMF文件
        
        Args:
            file_path: DMF文件路径
            
        Returns:
            bool: 解析是否成功
        """
        try:
            self.raw_data = self.parse_dmf_to_objects(file_path)
            if not self.raw_data:
                print(f"DMF文件解析失败: {file_path}")
                return False
                
            # 转换为与INF parser兼容的格式
            self._convert_to_compatible_format()
            print(f"✓ DMF文件解析成功: {file_path}")
            return True
            
        except Exception as e:
            print(f"DMF文件解析出错: {e}")
            return False

    @staticmethod
    def parse_dmf_to_objects(dmf_path: str) -> Dict[str, Any]:
        """
        解析 .dmf 文件，将信息读入到对应的 Python 对象中，
        并维护通道分类映射。

        Args:
            dmf_path (str): .dmf 文件的完整路径。

        Returns:
            dict: 包含解析后对象的字典，例如:
                  {
                      'analog_channels': {mno: AnalogChannel_obj, ...},
                      'status_channels': {mno: StatusChannel_obj, ...},
                      'buses': [Bus_obj, ...],
                      'lines': [Line_obj, ...],
                      'transformers': [Transformer_obj, ...],
                  }
                  如果文件不存在或解析失败，返回空字典。
        """

        try:
            # 尝试直接解析 DMF 文件
            tree = etree.parse(dmf_path)
            root = tree.getroot()
            logging.info(f"Successfully parsed DMF file: {dmf_path}")

        except etree.XMLSyntaxError as e:
            logging.warning(f"警告: 解析 DMF 文件 {dmf_path} 时发生 XML 语法错误: {e}")
            logging.info("尝试修复 DMF 文件格式...")
            try:
                with open(dmf_path, 'r', encoding='utf-8') as f:
                    content = f.read()

                # 移除 XML 声明行（假设在第一行）
                lines = content.splitlines()
                if lines and lines[0].strip().startswith('<?xml'):
                    fixed_content = '\n'.join(lines[1:])
                else:
                    fixed_content = content

                # 替换默认命名空间为带前缀的命名空间
                fixed_content = re.sub(
                    r'xmlns=("|\')(http://www.iec.ch/61850/2003/SCL)("|\')',
                    r'xmlns:scl=\1\2\3',
                    fixed_content
                )

                root = etree.fromstring(fixed_content)

            except Exception as fix_e:
                logging.error(f"错误: 尝试修复 DMF 文件失败: {fix_e}")
                return {}

        except FileNotFoundError:
            logging.error(f"错误: DMF 文件未找到在 {dmf_path}")
            return {}

        try:
            if root is not None:
                # 存储所有解析出的对象
                parsed_data: Dict[str, Any] = {
                    'analog_channels': {},
                    'status_channels': {},
                    'buses': [],
                    'lines': [],
                    'transformers': [],
                }
                bus_id_to_name = {}

                # --- 动态读取并处理命名空间 ---
                effective_namespaces = {}
                scl_uri = None

                # 查找 scl 命名空间 URI
                for prefix, uri in root.nsmap.items():
                    if uri == "http://www.iec.ch/61850/2003/SCL":
                        scl_uri = uri
                        effective_namespaces['scl'] = scl_uri
                        break

                if not scl_uri:
                    logging.error("错误: 无法确定 scl 命名空间的 URI。请检查 DMF 文件格式。")
                    return {}

                # 1. 解析 AnalogChannel 和 StatusChannel
                for ana_chn_elem in root.xpath('//scl:AnalogChannel', namespaces=effective_namespaces):
                    idx_cfg_str = ana_chn_elem.get('idx_cfg')
                    if idx_cfg_str:
                        idx_cfg = safe_int(idx_cfg_str)
                        if idx_cfg is not None:
                            props = {
                                k: safe_float(v) if k in ['freq', 'au', 'bu', 'primary', 'secondary'] else (
                                    safe_int(v) if k == 'idx_org' else v
                                )
                                for k, v in ana_chn_elem.attrib.items() if k != 'idx_cfg'
                            }
                            parsed_data['analog_channels'][idx_cfg] = AnalogChannel(idx_cfg=idx_cfg, **props)

                for sta_chn_elem in root.xpath('//scl:StatusChannel', namespaces=effective_namespaces):
                    idx_cfg_str = sta_chn_elem.get('idx_cfg')
                    if idx_cfg_str:
                        idx_cfg = safe_int(idx_cfg_str)
                        if idx_cfg is not None:
                            props = {
                                k: safe_int(v) if k == 'idx_org' else v
                                for k, v in sta_chn_elem.attrib.items() if k != 'idx_cfg'
                            }
                            parsed_data['status_channels'][idx_cfg] = StatusChannel(idx_cfg=idx_cfg, **props)

                # 2. 解析 Bus
                for bus_elem in root.xpath('//scl:Bus', namespaces=effective_namespaces):
                    bus_idx_str = bus_elem.get('idx')
                    if not bus_idx_str:
                        logging.warning(
                            f"发现 Bus 元素没有 idx 属性，跳过。XML: {etree.tostring(bus_elem, pretty_print=True).decode()}")
                        continue
                    bus_idx = safe_int(bus_idx_str)
                    if bus_idx is None:
                        continue
                    bus_name = bus_elem.get('bus_name', f"Bus_{bus_idx}")

                    bus_obj = Bus(
                        idx=bus_idx,
                        bus_name=bus_name,
                        sys_ID=bus_elem.get('sys_ID'),
                        srcRef=bus_elem.get('srcRef'),
                        VRtg=safe_float(bus_elem.get('VRtg')),
                        VRtgSnd=safe_float(bus_elem.get('VRtgSnd')),
                        VRtgSnd_Pos=bus_elem.get('VRtgSnd_Pos')
                    )
                    parsed_data['buses'].append(bus_obj)
                    bus_id_to_name[bus_idx_str] = bus_name

                    # 填充 ACVChn
                    for acv_chn_elem in bus_elem.xpath('scl:ACVChn', namespaces=effective_namespaces):
                        ua_idx = safe_int(acv_chn_elem.get('ua_idx'))
                        ub_idx = safe_int(acv_chn_elem.get('ub_idx'))
                        uc_idx = safe_int(acv_chn_elem.get('uc_idx'))
                        un_idx = safe_int(acv_chn_elem.get('un_idx'))
                        acv_obj = ACVChn(ua_idx, ub_idx, uc_idx, un_idx)
                        bus_obj.acv_chns.append(acv_obj)

                    # 填充 AnaChn
                    for ana_chn_elem in bus_elem.xpath('scl:AnaChn', namespaces=effective_namespaces):
                        idx_cfg_str = ana_chn_elem.get('idx_cfg')
                        if idx_cfg_str:
                            idx_cfg = safe_int(idx_cfg_str)
                            if idx_cfg is not None and idx_cfg in parsed_data['analog_channels']:
                                ana_channel_obj = parsed_data['analog_channels'][idx_cfg]
                                bus_obj.ana_chns.append(ana_channel_obj)
                            elif idx_cfg is not None:
                                logging.warning(f"Bus {bus_name} 引用了未定义的 AnalogChannel idx_cfg={idx_cfg}")

                    # 填充 StaChn
                    for sta_chn_elem in bus_elem.xpath('scl:StaChn', namespaces=effective_namespaces):
                        idx_cfg_str = sta_chn_elem.get('idx_cfg')
                        if idx_cfg_str:
                            idx_cfg = safe_int(idx_cfg_str)
                            if idx_cfg is not None and idx_cfg in parsed_data['status_channels']:
                                sta_channel_obj = parsed_data['status_channels'][idx_cfg]
                                bus_obj.sta_chns.append(sta_channel_obj)
                            elif idx_cfg is not None:
                                logging.warning(f"Bus {bus_name} 引用了未定义的 StatusChannel idx_cfg={idx_cfg}")

                # 3. 解析 Line
                for line_elem in root.xpath('//scl:Line', namespaces=effective_namespaces):
                    line_idx_str = line_elem.get('idx')
                    if not line_idx_str:
                        logging.warning(
                            f"发现 Line 元素没有 idx 属性，跳过。XML: {etree.tostring(line_elem, pretty_print=True).decode()}")
                        continue
                    line_idx = safe_int(line_idx_str)
                    if line_idx is None:
                        continue
                    line_name = line_elem.get('line_name', f"Line_{line_idx}")
                    bus_id_ref_str = line_elem.get('bus_ID')
                    bus_id_ref = safe_int(bus_id_ref_str) if bus_id_ref_str else None

                    connected_bus_name = bus_id_to_name.get(str(bus_id_ref),
                                                            'UnknownBus') if bus_id_ref else 'NoBusSpecified'
                    line_category_prefix = f"Line:{connected_bus_name}-{line_name}"

                    line_obj = Line(
                        idx=line_idx,
                        line_name=line_name,
                        sys_ID=line_elem.get('sys_ID'),
                        bus_ID=bus_id_ref,
                        srcRef=line_elem.get('srcRef'),
                        VRtg=safe_float(line_elem.get('VRtg')),
                        ARtg=safe_float(line_elem.get('ARtg')),
                        ARtgSnd=safe_float(line_elem.get('ARtgSnd')),
                        LinLen=safe_float(line_elem.get('LinLen')),
                        bran_num=safe_int(line_elem.get('bran_num'))
                    )
                    parsed_data['lines'].append(line_obj)

                    # 填充 RX, PX, CG
                    rx_elem = line_elem.xpath('scl:RX', namespaces=effective_namespaces)
                    if rx_elem:
                        line_obj.rx = RX(
                            r1=safe_float(rx_elem[0].get('r1')),
                            x1=safe_float(rx_elem[0].get('x1')),
                            r0=safe_float(rx_elem[0].get('r0')),
                            x0=safe_float(rx_elem[0].get('x0'))
                        )
                    px_elem = line_elem.xpath('scl:PX', namespaces=effective_namespaces)
                    if px_elem:
                        line_obj.px = PX(
                            px=safe_float(px_elem[0].get('px')),
                            px0=safe_float(px_elem[0].get('px0'))
                        )
                    cg_elem = line_elem.xpath('scl:CG', namespaces=effective_namespaces)
                    if cg_elem:
                        g1 = safe_float(cg_elem[0].get('g1'))
                        g0 = safe_float(cg_elem[0].get('g0'))
                        c1 = safe_float(cg_elem[0].get('c1'))
                        c0 = safe_float(cg_elem[0].get('c0'))

                        if g1 is not None and g0 is not None and c1 is not None and c0 is not None:
                            line_obj.cg = CG(c1=c1, c0=c0, g1=g1, g0=g0)
                        elif c1 is not None and c0 is not None:
                            line_obj.cg = CG(c1=c1, c0=c0)

                    # 填充 ACC_Bran
                    for acc_bran_elem in line_elem.xpath('scl:ACC_Bran', namespaces=effective_namespaces):
                        bran_obj = ACC_Bran(
                            bran_idx=safe_int(acc_bran_elem.get('bran_idx')),
                            dir=acc_bran_elem.get('dir'),
                            ia_idx=safe_int(acc_bran_elem.get('ia_idx')),
                            ib_idx=safe_int(acc_bran_elem.get('ib_idx')),
                            ic_idx=safe_int(acc_bran_elem.get('ic_idx')),
                            in_idx=safe_int(acc_bran_elem.get('in_idx'))
                        )
                        line_obj.acc_brans.append(bran_obj)

                        for phase_idx_attr in ['ia_idx', 'ib_idx', 'ic_idx', 'in_idx']:
                            phase_idx_str = acc_bran_elem.get(phase_idx_attr)
                            if phase_idx_str:
                                phase_idx = safe_int(phase_idx_str)

                    # 填充 ACVChn
                    for acv_chn_elem in line_elem.xpath('scl:ACVChn', namespaces=effective_namespaces):
                        ua_idx = safe_int(acv_chn_elem.get('ua_idx'))
                        ub_idx = safe_int(acv_chn_elem.get('ub_idx'))
                        uc_idx = safe_int(acv_chn_elem.get('uc_idx'))
                        un_idx = safe_int(acv_chn_elem.get('un_idx'))
                        acv_obj = ACVChn(ua_idx, ub_idx, uc_idx, un_idx)
                        line_obj.acv_chns.append(acv_obj)

                    # 填充 AnaChn
                    for ana_chn_elem in line_elem.xpath('scl:AnaChn', namespaces=effective_namespaces):
                        idx_cfg_str = ana_chn_elem.get('idx_cfg')
                        if idx_cfg_str:
                            idx_cfg = safe_int(idx_cfg_str)
                            if idx_cfg is not None and idx_cfg in parsed_data['analog_channels']:
                                ana_channel_obj = parsed_data['analog_channels'][idx_cfg]
                                line_obj.ana_chns.append(ana_channel_obj)
                            elif idx_cfg is not None:
                                logging.warning(f"Line {line_name} 引用了未定义的 AnalogChannel idx_cfg={idx_cfg}")

                    # 填充 StaChn
                    for sta_chn_elem in line_elem.xpath('scl:StaChn', namespaces=effective_namespaces):
                        idx_cfg_str = sta_chn_elem.get('idx_cfg')
                        if idx_cfg_str:
                            idx_cfg = safe_int(idx_cfg_str)
                            if idx_cfg is not None and idx_cfg in parsed_data['status_channels']:
                                sta_channel_obj = parsed_data['status_channels'][idx_cfg]
                                line_obj.sta_chns.append(sta_channel_obj)
                            elif idx_cfg is not None:
                                logging.warning(f"Line {line_name} 引用了未定义的 StatusChannel idx_cfg={idx_cfg}")

                # 4. 解析 Transformer
                for trm_elem in root.xpath('//scl:Transformer', namespaces=effective_namespaces):
                    trm_idx_str = trm_elem.get('idx')
                    if not trm_idx_str:
                        logging.warning(
                            f"发现 Transformer 元素没有 idx 属性，跳过。XML: {etree.tostring(trm_elem, pretty_print=True).decode()}")
                        continue
                    trm_idx = safe_int(trm_idx_str)
                    if trm_idx is None:
                        continue
                    trm_name = trm_elem.get('trm_name', f"Transformer_{trm_idx}")

                    trm_obj = Transformer(
                        idx=trm_idx,
                        trm_name=trm_name,
                        sys_ID=trm_elem.get('sys_ID'),
                        srcRef=trm_elem.get('srcRef'),
                        pwrRtg=safe_float(trm_elem.get('pwrRtg')),
                        winding_type=safe_int(trm_elem.get('winding_type'))
                    )
                    parsed_data['transformers'].append(trm_obj)

                    # 填充 TransformerWinding
                    for winding_elem in trm_elem.xpath('scl:TransformerWinding', namespaces=effective_namespaces):
                        location = winding_elem.get('location', 'Winding')
                        if location == 'High':
                            winding_tag = '高压侧'
                        elif location == 'Low':
                            winding_tag = '低压侧'
                        else:
                            winding_tag = location

                        winding_obj = TransformerWinding(
                            location=location,
                            srcRef=winding_elem.get('srcRef'),
                            VRtg=safe_float(winding_elem.get('VRtg')),
                            ARtg=safe_float(winding_elem.get('ARtg')),
                            bran_num=safe_int(winding_elem.get('bran_num')),
                            wG=winding_elem.get('wG')
                        )
                        trm_obj.windings.append(winding_obj)

                        # 填充 ACVChn
                        for acv_chn_elem in winding_elem.xpath('scl:ACVChn', namespaces=effective_namespaces):
                            ua_idx = safe_int(acv_chn_elem.get('ua_idx'))
                            ub_idx = safe_int(acv_chn_elem.get('ub_idx'))
                            uc_idx = safe_int(acv_chn_elem.get('uc_idx'))
                            un_idx = safe_int(acv_chn_elem.get('un_idx'))  # 补充 UN 支持
                            acv_obj = ACVChn(ua_idx, ub_idx, uc_idx, un_idx)
                            winding_obj.acv_chns.append(acv_obj)

                        # 填充 ACC_Bran
                        for acc_bran_elem in winding_elem.xpath('scl:ACC_Bran', namespaces=effective_namespaces):
                            bran_obj = ACC_Bran(
                                bran_idx=safe_int(acc_bran_elem.get('bran_idx')),
                                dir=acc_bran_elem.get('dir'),
                                ia_idx=safe_int(acc_bran_elem.get('ia_idx')),
                                ib_idx=safe_int(acc_bran_elem.get('ib_idx')),
                                ic_idx=safe_int(acc_bran_elem.get('ic_idx')),
                                in_idx=safe_int(acc_bran_elem.get('in_idx'))
                            )
                            winding_obj.acc_brans.append(bran_obj)

                            for phase_idx_attr in ['ia_idx', 'ib_idx', 'ic_idx', 'in_idx']:
                                phase_idx_str = acc_bran_elem.get(phase_idx_attr)
                                if phase_idx_str:
                                    phase_idx = safe_int(phase_idx_str)

                        # 填充 Igap
                        for igap_elem in winding_elem.xpath('scl:Igap', namespaces=effective_namespaces):
                            winding_obj.igaps.append(Igap(
                                zgap_idx=safe_int(igap_elem.get('zgap_idx')),
                                zsgap_idx=safe_int(igap_elem.get('zsgap_idx'))
                            ))

                    # 填充 AnaChn
                    for ana_chn_elem in trm_elem.xpath('scl:AnaChn', namespaces=effective_namespaces):
                        idx_cfg_str = ana_chn_elem.get('idx_cfg')
                        if idx_cfg_str:
                            idx_cfg = safe_int(idx_cfg_str)
                            if idx_cfg is not None and idx_cfg in parsed_data['analog_channels']:
                                ana_channel_obj = parsed_data['analog_channels'][idx_cfg]
                                trm_obj.ana_chns.append(ana_channel_obj)
                            elif idx_cfg is not None:
                                logging.warning(
                                    f"Transformer {trm_name} 引用了未定义的 AnalogChannel idx_cfg={idx_cfg}")

                    # 填充 StaChn
                    for sta_chn_elem in trm_elem.xpath('scl:StaChn', namespaces=effective_namespaces):
                        idx_cfg_str = sta_chn_elem.get('idx_cfg')
                        if idx_cfg_str:
                            idx_cfg = safe_int(idx_cfg_str)
                            if idx_cfg is not None and idx_cfg in parsed_data['status_channels']:
                                sta_channel_obj = parsed_data['status_channels'][idx_cfg]
                                trm_obj.sta_chns.append(sta_channel_obj)

                return parsed_data
            else:
                return {}

        except Exception as e:
            logging.exception(e)
            return {}

    def _convert_to_compatible_format(self):
        """将DMF原始数据转换为与INF parser兼容的格式"""
        
        # 转换线路数据
        self.lines = []
        for line_obj in self.raw_data.get('lines', []):
            line_dict = {
                'dev_id': str(line_obj.idx),
                'dev_name': line_obj.line_name,
                'dev_type': 'line',
                'bus_id': str(line_obj.bus_ID) if line_obj.bus_ID else None,
                'current_channels': [],
                'voltage_channels': [],
                'status_channels': []
            }
            
            # 提取电流通道
            for acc_bran in line_obj.acc_brans:
                current_channels = [
                    acc_bran.ia_idx, acc_bran.ib_idx, 
                    acc_bran.ic_idx, acc_bran.in_idx
                ]
                # 过滤None值
                current_channels = [ch for ch in current_channels if ch is not None]
                line_dict['current_channels'].extend(current_channels)
            
            # 提取电压通道
            for acv_chn in line_obj.acv_chns:
                voltage_channels = [
                    acv_chn.ua_idx, acv_chn.ub_idx,
                    acv_chn.uc_idx, acv_chn.un_idx
                ]
                # 过滤None值
                voltage_channels = [ch for ch in voltage_channels if ch is not None]
                line_dict['voltage_channels'].extend(voltage_channels)
            
            # 提取状态通道
            for sta_chn in line_obj.sta_chns:
                if hasattr(sta_chn, 'idx_cfg') and sta_chn.idx_cfg is not None:
                    line_dict['status_channels'].append(sta_chn.idx_cfg)
                    
            self.lines.append(line_dict)
        
        # 转换母线数据
        self.buses = []
        for bus_obj in self.raw_data.get('buses', []):
            bus_dict = {
                'dev_id': str(bus_obj.idx),
                'dev_name': bus_obj.bus_name,
                'dev_type': 'bus',
                'voltage_channels': [],
                'status_channels': []
            }
            
            # 提取电压通道
            for acv_chn in bus_obj.acv_chns:
                voltage_channels = [
                    acv_chn.ua_idx, acv_chn.ub_idx,
                    acv_chn.uc_idx, acv_chn.un_idx
                ]
                # 过滤None值
                voltage_channels = [ch for ch in voltage_channels if ch is not None]
                bus_dict['voltage_channels'].extend(voltage_channels)
            
            # 提取状态通道
            for sta_chn in bus_obj.sta_chns:
                if hasattr(sta_chn, 'idx_cfg') and sta_chn.idx_cfg is not None:
                    bus_dict['status_channels'].append(sta_chn.idx_cfg)
                    
            self.buses.append(bus_dict)
        
        # 转换变压器数据
        self.transformers = []
        for trm_obj in self.raw_data.get('transformers', []):
            trm_dict = {
                'dev_id': str(trm_obj.idx),
                'dev_name': trm_obj.trm_name,
                'dev_type': 'transformer',
                'winding_num': len(trm_obj.windings),
                'voltage_hv_channels': [],
                'voltage_mv_channels': [],
                'voltage_lv_channels': [],
                'current_hv_channels': [],
                'current_mv_channels': [],
                'current_lv_channels': [],
                'oth_achns': [],
                'oth_status_channels': [],
                'status_channels': []
            }
            
            # 处理绕组数据
            for winding in trm_obj.windings:
                location = winding.location.upper()
                
                # 提取电压通道
                voltage_channels = []
                for acv_chn in winding.acv_chns:
                    channels = [
                        acv_chn.ua_idx, acv_chn.ub_idx,
                        acv_chn.uc_idx, acv_chn.un_idx
                    ]
                    voltage_channels.extend([ch for ch in channels if ch is not None])
                
                # 提取电流通道
                current_channels = []
                for acc_bran in winding.acc_brans:
                    channels = [
                        acc_bran.ia_idx, acc_bran.ib_idx,
                        acc_bran.ic_idx, acc_bran.in_idx
                    ]
                    current_channels.extend([ch for ch in channels if ch is not None])
                
                # 根据绕组位置分配通道
                if location in ['HIGH', 'HV', 'H']:
                    trm_dict['voltage_hv_channels'].extend(voltage_channels)
                    trm_dict['current_hv_channels'].extend(current_channels)
                elif location in ['MIDDLE', 'MV', 'M', 'MED']:
                    trm_dict['voltage_mv_channels'].extend(voltage_channels)
                    trm_dict['current_mv_channels'].extend(current_channels)
                elif location in ['LOW', 'LV', 'L']:
                    trm_dict['voltage_lv_channels'].extend(voltage_channels)
                    trm_dict['current_lv_channels'].extend(current_channels)
                else:
                    # 默认分配给高压侧
                    trm_dict['voltage_hv_channels'].extend(voltage_channels)
                    trm_dict['current_hv_channels'].extend(current_channels)
            
            # 提取其他模拟通道
            for ana_chn in trm_obj.ana_chns:
                if hasattr(ana_chn, 'idx_cfg') and ana_chn.idx_cfg is not None:
                    trm_dict['oth_achns'].append(ana_chn.idx_cfg)
            
            # 提取其他状态通道
            for sta_chn in trm_obj.sta_chns:
                if hasattr(sta_chn, 'idx_cfg') and sta_chn.idx_cfg is not None:
                    trm_dict['oth_status_channels'].append(sta_chn.idx_cfg)
                    trm_dict['status_channels'].append(sta_chn.idx_cfg)
                    
            self.transformers.append(trm_dict)
            
        # 设置文件信息
        self.file_info = {
            'total_lines': len(self.lines),
            'total_buses': len(self.buses),
            'total_transformers': len(self.transformers),
            'data_source': 'DMF'
        }
    
    def get_lines_data(self) -> List[Dict]:
        """获取线路数据，格式与INF parser兼容"""
        return self.lines
    
    def get_buses_data(self) -> List[Dict]:
        """获取母线数据，格式与INF parser兼容"""
        return self.buses
    
    def get_transformers_data(self) -> List[Dict]:
        """获取变压器数据，格式与INF parser兼容"""
        return self.transformers
    
    def get_raw_dmf_data(self) -> Dict[str, Any]:
        """获取原始DMF解析数据"""
        return self.raw_data


def parse_dmf_to_objects(dmf_file):
    return DMFParser.parse_dmf_to_objects(dmf_file)

# --- Test Usage ---
if __name__ == '__main__':
    # 确保 NPS693_RCD_1288_20240926_111408_160_B.xml 文件在正确的位置
    # For testing, save the provided XML content as 'NPS693_RCD_1288_20240926_111408_160_B.xml'
    dmf_test_file = "../data/NPS693_RCD_1288_20240926_111408_160_B.DMF"

    print(f"Parsing {dmf_test_file} to objects...")
    parsed_data_objects = parse_dmf_to_objects(dmf_test_file)

    if parsed_data_objects:
        print("\n--- Parsed Buses ---")
        for bus_obj in parsed_data_objects['buses']:
            print(bus_obj)
            for acv_chn in bus_obj.acv_chns:
                print(f"  - {acv_chn}")
            for ana_chn in bus_obj.ana_chns:
                print(f"  - AnaChn (idx_cfg: {ana_chn.idx_cfg}, category: {ana_chn.category})")
            for sta_chn in bus_obj.sta_chns:
                print(f"  - StaChn (idx_cfg: {sta_chn.idx_cfg}, category: {sta_chn.category})")

        print("\n--- Parsed Lines ---")
        for line_obj in parsed_data_objects['lines']:
            print(line_obj)
            if line_obj.rx:
                print(f"  - RX: r1={line_obj.rx.r1}, x1={line_obj.rx.x1}")
            for acc_bran in line_obj.acc_brans:
                print(f"  - {acc_bran}")
            for ana_chn in line_obj.ana_chns:
                print(f"  - AnaChn (idx_cfg: {ana_chn.idx_cfg}, category: {ana_chn.category})")
            for sta_chn in line_obj.sta_chns:
                print(f"  - StaChn (idx_cfg: {sta_chn.idx_cfg}, category: {sta_chn.category})")
            for acv_chn in line_obj.acv_chns:  # 打印Line下的ACVChn
                print(f"  - {acv_chn}")

        print("\n--- Parsed Transformers ---")
        for trm_obj in parsed_data_objects['transformers']:
            print(trm_obj)
            for winding in trm_obj.windings:
                print(f"  - {winding}")
                for acv_chn in winding.acv_chns:
                    print(f"    - {acv_chn}")
                for acc_bran in winding.acc_brans:
                    print(f"    - {acc_bran}")
                for igap in winding.igaps:
                    print(f"    - {igap}")
            for ana_chn in trm_obj.ana_chns:
                print(f"  - AnaChn (idx_cfg: {ana_chn.idx_cfg}, category: {ana_chn.category})")
            for sta_chn in trm_obj.sta_chns:
                print(f"  - StaChn (idx_cfg: {sta_chn.idx_cfg}, category: {sta_chn.category})")
